<?php

	class ContentEngine_ImageUtility {

		private $_uploadPath;
		private $_urlPath;
		private $_maxWidth = 650;

		function __construct() {
			$datePart = date( 'Y' ) . '/' . date( 'm' );
			$this->_uploadPath = APP_PATH . 'public/media/images/' . $datePart;
			$this->_urlPath = HOME_PATH . 'media/images/' . $datePart;
			if( !is_dir( $this->_uploadPath ) ) {
				@mkdir( $this->_uploadPath, 0777, true );
			}
		}

		public function uploadImageFromFile( $fileInfo, $imageTitle = '', $index = 0, $process = true ) {
	        if( is_array( $fileInfo[ 'type' ] ) ) {
	            $fileInfo = array(
	                'name' => $fileInfo['name'][$index],
	                'type' => $fileInfo['type'][$index],
	                'tmp_name' => $fileInfo['tmp_name'][$index],
	                'error' => $fileInfo['error'][$index],
	                'size' => $fileInfo['size'][$index]
	            );
	        }
	        if( $fileInfo[ 'error' ] !== UPLOAD_ERR_OK ) {
	            throw new Exception( self::getUploadErrorMessage( $fileInfo[ 'error' ] ) );
	        } else if (array_search($fileInfo['type'], array('image/pjpeg', 'image/jpeg', 'image/png', 'image/gif', 'image/bmp')) === false) {
	            throw new Exception('Unsuported file type "' . $fileInfo['type'] . '"!');
	        }
	
	        $extension = explode("/", $fileInfo['type']);
	        $extension = $extension[1];
	
	        if (array_search($extension, array('pjpeg', 'jpeg')) !== false) {
	            $extension = "jpg";
	        }
	
	        if (!$imageTitle) {
	            $imageTitle = explode( '.', $fileInfo['name']);
	            $imageTitle = ucwords( str_replace('-', ' ', $imageTitle[0]));
	        }
	
	        $imageSlug = str_replace( '-', '_', sanitizeWithDashes( $imageTitle ) ) . '_' . self::randomStringGenerator( 5, true );
	
	        $filePath = $fileInfo[ 'tmp_name' ];
	        $thumb = PhpThumbFactory::create( $filePath, array( 'resizeUp' => true ) );
	        $imageDimension = $thumb->getCurrentDimensions();
	        $result = array();
	        if( ( $imageDimension['width'] > $this->_maxWidth ) && $process ) {
	            $cropImageHeight = round( ( $this->_maxWidth / $imageDimension['width'] ) * $imageDimension[ 'height' ] );
	            $thumb->resize( $this->_maxWidth, $cropImageHeight );
	            $thumb->save( $this->_uploadPath . '/' . $imageSlug . "." . $extension );
	            @move_uploaded_file( $fileInfo[ 'tmp_name' ], $this->_uploadPath . "/{$imageSlug}_original.$extension" );
                $result['image'] = array(
                    'uri' => $this->_urlPath .  "/$imageSlug.$extension",
                    'width' => $this->_maxWidth,
                    'height' => $cropImageHeight
                );
                $result['original'] = array(
                    'uri' => $this->saveFileOnS3( $this->_urlPath .  "/$imageSlug" . "_original." . $extension ),
                    'width' => $imageDimension['width'],
                    'height' => $imageDimension['height']
                );
	        } else {
	            @move_uploaded_file( $fileInfo[ 'tmp_name' ], $this->_uploadPath . "/$imageSlug.$extension" );
	            $result['image'] = array(
	                'uri' => $this->_urlPath .  "/$imageSlug.$extension",
	                'width' => $imageDimension[ 'width' ],
	                'height' => $imageDimension[ 'height' ]
	            );
	        }
	        if (is_uploaded_file($fileInfo['tmp_name'])) {
	            @unlink( $filePath );
	        }
	        return $this->saveUploadResults( $result, $imageTitle );
	    }

		public static function uploadImageFromUrl( $imageUrl, $imageTitle = '', $process = true ) {
	        if( !@parse_url( $url ) ) {
	            throw new Exception( "'$imageUrl' does not seem to be a valid url!" );
	        }
	        if( !@getimagesize( $imageUrl ) ) {
	            throw new Exception( "'$imageUrl' is not a valid image url or not accessible right now!" );
	        }
	
	        $extension = explode( '/', $fileInfo[ 'type' ] );
	        $extension = $extension[ 1 ];
	
	        if( array_search( $extension, array( 'pjpeg', 'jpeg' ) ) !== false ) {
	            $extension = "jpg";
	        }
	
	        if (!$imageTitle) {
	            $imageTitle = explode( '.', $fileInfo['name']);
	            $imageTitle = ucwords( str_replace('-', ' ', $imageTitle[0]));
	        }

	        $imageSlug = str_replace( '-', '_', sanitizeWithDashes( $imageTitle ) ) . '_' . self::randomStringGenerator( 5, true );

	        if( $tempLocation = self::downloadImage( $imageUrl ) ) {
	            $imageName = explode( DIRECTORY_SEPARATOR, $tempLocation );
	            $result = $this->uploadImageFromFile(array(
	                'name' => $imageName[count($imageName) - 1],
	                'type' => mime_content_type($tempLocation),
	                'tmp_name' => $tempLocation,
	                'error' => 0,
	                'size' => filesize($tempLocation)
	                    ), $imageTitle, 0, $process);
	            @unlink($tempLocation);
	            return $result;
	        } else {
	            throw new Exception( "'$imageUrl' could not be saved locally to '$tempLocation'!" );
	        }
			return self::saveUploadResults( $libImage->uploadImageFromUrl( $imageUrl, $imageTitle, $process ), $imageTitle );
		}

	    /**
	     * Downloads image from remote server to local.
	     * @param string $url
	     */
	    public static function downloadImage( $url, $path ) {
	        $ch = curl_init( $url );
	        curl_setopt( $ch, CURLOPT_HEADER, 0 );
	        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
	        curl_setopt( $ch, CURLOPT_BINARYTRANSFER, 1 );
	        curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 );
	        curl_setopt( $ch, CURLOPT_FAILONERROR, 1 );
	        curl_setopt( $ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20100101 Firefox/12.0' );
	        $rawdata = curl_exec( $ch );
	        if( curl_getinfo( $ch, CURLINFO_HTTP_CODE ) == 200 ) {
	            curl_close( $ch );
	            $fullpath = self::_getTempFileName();
	            $fp = fopen( $fullpath, 'w' );
	            fwrite( $fp, $rawdata );
	            fclose( $fp );
	            return $fullpath;
	        }
	        curl_close( $ch );
	        return false;
	    }

		private function saveUploadResults( $result, $imageTitle ) {
			$image = getDb( 'image', 'add' );
			$image->set( 'imageUri||' . str_replace( IMAGE_PUBLIC_LOCATION, '', $result[ 'image' ][ 'uri' ] ), "imageTitle||$imageTitle", 'imageWidth||' . $result[ 'image' ][ 'width' ], 'imageHeight||' . $result[ 'image' ][ 'height' ] );
			$imageId = $image->getLastInsertedId();
			if( isset( $result[ 'original' ] ) ) {
				$imageDimension = getDb( 'imageDimension', 'add' );
				$imageDimension->set( "imageId||$imageId", 'imageUri||' . str_replace( IMAGE_PUBLIC_LOCATION, '', $result[ 'original' ][ 'uri' ] ), 'imageWidth||' . $result[ 'original' ][ 'width' ], 'imageHeight||' . $result[ 'original' ][ 'height' ] );
			}
			return $imageId;
		}

		public static function getScaledImage( $imageIdOrUri, $width = false, $height = false ) {
			$image = new ContentEngine_DO_Image();
			is_numeric( $imageIdOrUri ) ? $image->set( "imageId||$imageIdOrUri" ) : $image->set( "imageUri||$imageIdOrUri" );
			if( $image->getResultCount() < 1 ) {
				return '';
			}
			if( $width == false ) {
				return $image->getImageUri();
			}
			if( $height === false ) {
				$height = ( int ) ( ( $width * $image->getImageHeight() ) / $image->getImageWidth() );
			}
			if( $image->getImageWidth() == $width && $image->getImageHeight() == $height ) {
				return $image->getImageUri();
			}

			$imageName = explode( '/', $image->getImageUri() );
			$imageName = $imageName[ count( $imageName ) - 1 ];
			$extension = explode( '.', $imageName );
			$extension = '.' . $extension[ count( $extension ) - 1 ];
			$imageName = str_replace( $extension, '', $imageName );
			$path = str_replace( 'http://', '', trim( str_replace( $imageName . $extension, '', $image->getImageUri() ), '/' ) );
			$newName = $imageName . '_' . $width . 'x' . $height . $extension;

			try {
				$imageDimension = new ContentEngine_DO_ImageDimension();
				$imageDimension->set( 'imageId||' . $image->getImageId(), "imageWidth||$width", "imageHeight||$height" );
				if( $imageDimension->getResultCount() > 0 ) {
					return $imageDimension->getImageUri();
				}
				$imageDimension = new ContentEngine_DO_ImageDimension();
				$imageDimension->set( 'imageId||' . $image->getImageId(), 'imageUri||' . $path . '/' . $imageName . '_original' . $extension );
				$imageUrl = $imageDimension->getResultCount() > 0 ? $imageDimension->getImageUri() : $image->getImageUri();
				$libImage = Betaout_Image::getInstance( AMAZON_ID, AMAZON_SECRET_KEY, S3_BUCKET );
				$imageLocation = $libImage->downloadImage( $imageUrl );
				if( $imageLocation ) {
					$scaledImage = $libImage->resizeImage( $width, $height, $imageLocation, true );
					$path = str_replace( '.s3.amazonaws.com', '', $path );
					$uri = S3_IMAGE_PUBLIC_LOCATION . $libImage->saveFileOnS3( $scaledImage, $newName, str_replace( S3_BUCKET, '', $path ) );
					@unlink( $imageLocation );
					@unlink( $scaledImage );
					$imageDimension = new ContentEngine_DO_ImageDimension( 'add' );
					$imageDimension->set( 'imageId||' . $image->getImageId(), "imageUri||$uri", "imageWidth||$width", "imageHeight||$height" );
					return $uri;
				} else {
					return '';
				}
			} catch( Exception $ex ) {
				return '';
			}
		}

	    /**
	     * Returns the error message for upload file error.
	     * @param integer $errorCode
	     */
	    public static function getUploadErrorMessage( $errorCode ) {
	        switch( $errorCode ) {
	            case UPLOAD_ERR_INI_SIZE: {
	                    return 'The uploaded file exceeds the upload_max_filesize directive! It should not be more than ' . ( ini_get('upload_max_filesize') ) . '.';
	                } case UPLOAD_ERR_FORM_SIZE: {
	                    return 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form';
	                } case UPLOAD_ERR_PARTIAL: {
	                    return 'The uploaded file was only partially uploaded';
	                } case UPLOAD_ERR_NO_FILE: {
	                    return 'No file was uploaded';
	                } case UPLOAD_ERR_NO_TMP_DIR: {
	                    return 'Missing a temporary folder';
	                } case UPLOAD_ERR_CANT_WRITE: {
	                    return 'Failed to write file to disk';
	                } case UPLOAD_ERR_EXTENSION: {
	                    return 'File upload stopped by extension';
	                } default: {
	                    return 'Unknown upload error';
	                }
	        }
	    }

	    public static function randomStringGenerator( $length, $small=false ) {
	        $i = 0;
	        $random_str = '';
	        $a_to_z = 'aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ123456789';
	        $max = strlen($a_to_z) - 1;
	        while ($i != $length) {
	            $rand = mt_rand(0, $max);
	            $random_str .= $a_to_z[$rand];
	            $i++;
	        }
	        return $small ? strtolower($random_str) : $random_str;
	    }
	}

	ini_set( 'gd.jpeg_ignore_warning', 1 );
	if( !function_exists( 'mime_content_type' ) ) {
	    function mime_content_type($filename) {
	        $finfo = finfo_open( FILEINFO_MIME );
	        $mimetype = finfo_file( $finfo, $filename );
	        finfo_close( $finfo );
	        return $mimetype;
	    }
	}